package com.yuma.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuma.tingshu.account.client.UserAccountFeignClient;
import com.yuma.tingshu.common.constant.RedisConstant;
import com.yuma.tingshu.common.execption.YumaException;
import com.yuma.tingshu.common.result.ResultCodeEnum;
import com.yuma.tingshu.common.util.AuthContextHolder;
import com.yuma.tingshu.model.order.OrderInfo;
import com.yuma.tingshu.model.user.UserInfo;
import com.yuma.tingshu.model.user.UserPaidAlbum;
import com.yuma.tingshu.model.user.UserPaidTrack;
//import com.yuma.tingshu.user.login.LoginClient;
//import com.yuma.tingshu.user.login.LoginType;
//import com.yuma.tingshu.user.login.LoginVo;
import com.yuma.tingshu.model.user.UserSubscribe;
import com.yuma.tingshu.user.login.LoginType;
import com.yuma.tingshu.user.mapper.UserInfoMapper;
import com.yuma.tingshu.user.mapper.UserPaidAlbumMapper;
import com.yuma.tingshu.user.mapper.UserPaidTrackMapper;
import com.yuma.tingshu.user.mapper.UserSubscribeMapper;
import com.yuma.tingshu.user.service.UserInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuma.tingshu.vo.user.UserInfoVo;
import jakarta.annotation.Resources;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    /*@Autowired
    private LoginClient loginClient;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;*/

    @Autowired
    private UserInfoMapper userInfoMapper;

    // 微信码服务
    @Autowired
    private WxMaService wxMaService;

    // 远程调用账号，进行账号初始化
    @Autowired
    private UserAccountFeignClient userAccountFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;
    @Autowired
    private UserSubscribeMapper userSubscribeMapper;

    @Override
    public Page<UserSubscribe> findUserSubscribePage(Integer page, Integer limit) {
        Long userId = AuthContextHolder.getUserId();
        Page<UserSubscribe> UserSubscribePage = userSubscribeMapper.findUserSubscribePage(new Page<>(page, limit), userId);
        return UserSubscribePage;
    }

    @Transactional
    @Override
    public void updateVipExpireStat() {
        UserInfo userInfo = new UserInfo();
        userInfo.setIsVip(0);
        /**
         * 第一个参数，更新对象
         * 第二个参数，查询条件
         */
        this.update(userInfo, new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getIsVip, 1)
                .lt(UserInfo::getVipExpireTime, LocalDateTime.now()));
    }

    @Override
    public List<Long> getPaidTracksIdByAlbum(Long albumId) {
        Long userId = AuthContextHolder.getUserId();
        if (userId == null) {
            return null;
        }

        List<UserPaidTrack> userPaidTracks = this.userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
                .eq(UserPaidTrack::getAlbumId, albumId)
                .eq(UserPaidTrack::getUserId, userId));

        List<Long> list = userPaidTracks.stream().map(UserPaidTrack::getTrackId).toList();

        return list;
    }

    @Override
    public Boolean isPaidAlbum(Long albumId) {
        Long userId = AuthContextHolder.getUserId();
        return userPaidAlbumMapper.exists(new LambdaQueryWrapper<UserPaidAlbum>()
                .eq(UserPaidAlbum::getAlbumId, albumId)
                .eq(UserPaidAlbum::getUserId, userId));
    }

    @Transactional
    @Override
    public Map<String, Object> wxLogin(String code) throws Exception {
        //1.根据code,appid和appsecret调用微信接口  获取openId
        WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
        String openid = sessionInfo.getOpenid();
        // 2.如果获取openid失败，重新回调登陆页面
        //StringUtils.isEmpty(str)是否“无内容”（null 或 ""）
        if (StringUtils.isBlank(openid)/*是否“无意义内容”（null、空、全空白）*/) {
            throw new YumaException(ResultCodeEnum.LOGIN_AUTH);
        }
        // 3.根据openId到user_info数据库表中获取用户信息userinfo
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getWxOpenId, openid));
        //4.如果用户信息userinfo为空，说明还没注册,进行隐式注册
        if (userInfo == null) {
            // 隐式注册
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openid);
            // 在RedisConstrant中配置一个USER_NICKNAME_KEY = "user:nickname";
            //从10001,顺序递增,UUID不行,随机,太长,不是递增。redis定义一个key-value,value的初始值10000
            /**
             * redisTemplate.opsForValue()获取操作 RedisString 类型数据的工具
             * .set(key, value)存储一个键值对
             * .get(key)获取值
             * .increment(key)数值自增（+1）
             * .decrement(key)数值自减（-1）
             * .setIfAbsent(key, value)如果 key 不存在才设置（类似 SETNX）
             * .set(key, value, timeout, unit)设置值并带过期时间
             */
            userInfo.setNickname("听友" + redisTemplate.opsForValue().increment(RedisConstant.USER_NICKNAME_KEY));
            userInfo.setAvatarUrl("https://img1.baidu.com/it/u=958010751,3701981661&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1739379600&t=150e5182e762861c6b6f16a0006dbd83");
            userInfo.setStatus("1");
            userInfoMapper.insert(userInfo);
            // TODO: 初始化账户信息
            userAccountFeignClient.init(userInfo.getId());//RPC远程调用
            //int i = 1/0;
        }
        //5.生成令牌，将令牌为key主要配分，以userinfo为value，保存到redis中
        String token = UUID.randomUUID().toString();
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token, userInfoVo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        //6.返回令牌给客户端(只返回令牌，不返回用户信息)
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        return map;
    }

    /*//@GlobalTransactional
    @Transactional
    @Override
    public Map<String, String> login(String code) throws WxErrorException {
        LoginVo loginVo = new LoginVo();
        loginVo.setCode(code);
        return this.loginClient.login(LoginType.WX_LOGIN, loginVo);
    }

    @Override
    public Boolean isPaidAlbum(Long albumId) {
        Long userId = AuthContextHolder.getUserId();
        return this.userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>()
                .eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId)) > 0;
    }

    @Override
    public List<UserPaidTrack> getPaidTracks(Long albumId) {
        Long userId = AuthContextHolder.getUserId();
        return this.userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
                .eq(UserPaidTrack::getAlbumId, albumId).eq(UserPaidTrack::getUserId, userId));
    }

    @Override
    public void updateExpiredVipStatus() {
        UserInfo userInfo = new UserInfo();
        userInfo.setIsVip(0);
        // 今天凌晨时间
        LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        Date date = Date.from(localDateTime.toInstant(ZoneOffset.UTC));
        // 如果vip的过期时间小于今天凌晨，说明vip的过期时间是今天以前
        this.update(userInfo, new LambdaUpdateWrapper<UserInfo>().eq(UserInfo::getIsVip, 1).le(UserInfo::getVipExpireTime, date));
    }*/
}
